package com.smart.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.smart.common.enums.BooleanEnum;
import com.smart.common.enums.ProjectAuditStatusEnum;
import com.smart.common.enums.ProjectAuditTypeEnum;
import com.smart.common.enums.SmsTemplateEnum;
import com.smart.common.utils.AssertUtil;
import com.smart.context.SessionContext;
import com.smart.mapper.ProjectChangeReviewMapper;
import com.smart.mapper.ProjectMapper;
import com.smart.model.convert.ProjectConvert;
import com.smart.model.domain.ProjectChangeReviewDO;
import com.smart.model.domain.ProjectDO;
import com.smart.model.domain.ProjectStatusAxisDO;
import com.smart.model.dtomapper.ProjectChangeReviewDtoMapper;
import com.smart.model.dtomapper.ProjectDtoMapper;
import com.smart.model.request.ProjectChangeReviewRequest;
import com.smart.model.request.ProjectRequest;
import com.smart.model.vo.ProjectChangeReviewVO;
import com.smart.model.vo.ProjectVO;
import com.smart.service.ProjectReportService;
import com.smart.service.ProjectStatusAxisService;
import com.smart.service.SuperviseProjectService;
import com.smart.utils.DateUtils;
import com.smart.utils.SmsUtil;
import com.smart.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

import static com.smart.utils.PageUtils.getOrderBy;

/**
 * @author: zyh
 * @date: 2023-06-20
 */
@Slf4j
@Service
public class SuperviseProjectServiceImpl  implements SuperviseProjectService {

    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectChangeReviewMapper changeReviewMapper;
    @Autowired
    private ProjectReportService reportService;
    @Autowired
    private ProjectStatusAxisService axisService;
    @Autowired
    private ProjectTempTaskServiceImpl tempTaskService;

    /**
     * 新项目审核
     * @param request
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String newProjectExamine(ProjectRequest request, HttpServletRequest req) {
        Boolean examine = request.getExamine();
        if (examine){
            if (org.springframework.util.ObjectUtils.isEmpty(request.getId())){
                AssertUtil.assertTrue(false,"id不能为空");
            }
            String projectNumber = request.getProjectNumber();
            AssertUtil.assertTrue(StringUtil.isValidProjectNumber(projectNumber),"项目编号为10位以内的字母或数字的组合");
            int count = projectMapper.selectProNum(projectNumber,request.getId());
            AssertUtil.assertTrue(count<1,"项目编号已存在");
            ProjectDO projectDO = ProjectDtoMapper.INSTANCE.request2DO(request);
            projectDO.setAuditStatus(ProjectAuditStatusEnum.PASS.name());
            projectDO.setAuditType(ProjectAuditTypeEnum.NORMAL.name());
            projectDO.setUpdateUser(SessionContext.getSuperviseUserId());
            projectDO.setUpdateTime(DateUtils.getNowDate());
            projectDO.setValid(BooleanEnum.TRUE.getCode());
            projectMapper.updateDO(projectDO);
            //项目联系人
            String shigongContactPhone = projectDO.getShigongContactPhone();
            //项目责任人
            String shigongHeadPhone = projectDO.getShigongHeadPhone();
            List<String> phoneList = new ArrayList<>();
            phoneList.add(shigongContactPhone);
            phoneList.add(shigongHeadPhone);

            LocalDateTime now = LocalDateTime.now(); // 获取当前时间
            // 获取本周五的0点时间
            LocalDateTime fridayMidnight = now.with(DayOfWeek.FRIDAY).with(LocalTime.MIDNIGHT);
            if (now.isBefore(fridayMidnight)) {
                //周报提报
                reportService.createWeeklyTask(projectDO.getId());
            }
            //临时任务
            tempTaskService.createTempTask(projectDO.getId());
            SmsUtil.sendMessage(phoneList, SmsTemplateEnum.SMS_463146263);
            return "项目已新建成功";
        }else {
            ProjectDO projectDO = ProjectDtoMapper.INSTANCE.request2DO(request);
            projectDO.setProjectNumber(null);
            projectDO.setUpdateUser(SessionContext.getSuperviseUserId());
            projectDO.setUpdateTime(DateUtils.getNowDate());
            projectDO.setValid(BooleanEnum.FALSE.getCode());
            projectDO.setAuditStatus(ProjectAuditStatusEnum.REJECT.name());
            projectDO.setAuditType(ProjectAuditTypeEnum.NORMAL.name());
            projectMapper.updateDO(projectDO);
            return "已将该项目标记为无效注册";
        }
    }

    /**
     * 查询云服务项目编辑审核内容
     * @param id
     * @return
     */
    @Override
    public ProjectChangeReviewVO selectProjectChange(long id) {
        List<ProjectChangeReviewDO> list = changeReviewMapper.selectByProjectId(id);
        ProjectChangeReviewDO extracted = extracted(list);
        if (!ObjectUtils.isEmpty(extracted)){
            ProjectChangeReviewVO projectChangeReviewVO = ProjectChangeReviewDtoMapper.INSTANCE.do2VO(extracted);
            return projectChangeReviewVO;
        }
        return new ProjectChangeReviewVO();
    }


    /**
     * 项目编辑审核
     * @param request
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object oldProjectExamine(ProjectChangeReviewRequest request, HttpServletRequest req) {
        Long projectId = request.getProjectId();
        Long id = request.getId();
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(id),"id不能为空");
        Long userId = SessionContext.getSuperviseUserId();
        ProjectChangeReviewDO changeReviewDO = new ProjectChangeReviewDO();
        changeReviewDO.setId(id);
        changeReviewDO.setProjectId(projectId);
        changeReviewDO.setUpdateUser(userId);
        changeReviewDO.setUpdateTime(DateUtils.getNowDate());
        ProjectDO projectDO = new ProjectDO();
        projectDO.setId(projectId);
        projectDO.setUpdateUser(userId);
        projectDO.setUpdateTime(DateUtils.getNowDate());
        Boolean constructionAuditStatus = request.getConstructionAuditStatus();
        Boolean shigongHeadNameAuditStatus = request.getShigongHeadNameAuditStatus();
        ProjectDO aDo = new ProjectDO();
        aDo.setId(projectId);
        aDo.setUpdateUser(userId);
        aDo.setUpdateTime(DateUtils.getNowDate());
        aDo.setAuditType(ProjectAuditTypeEnum.NORMAL.name());
        aDo.setAuditStatus(ProjectAuditStatusEnum.PASS.name());
        if (!ObjectUtils.isEmpty(constructionAuditStatus)) {
            if (constructionAuditStatus) {
                String constructionStatusNow = request.getConstructionStatusNow();
                if ("RUNNING".equals(constructionStatusNow) || "WAIT_ACCEPT".equals(constructionStatusNow)){
                    ProjectDO project = projectMapper.selectDOById(projectId);
                    String constructionStatus = project.getConstructionStatus();
                    if (!"RUNNING".equals(constructionStatus) && !"WAIT_ACCEPT".equals(constructionStatus)){
                        LocalDateTime now = LocalDateTime.now(); // 获取当前时间
                        // 获取本周五的0点时间
                        LocalDateTime fridayMidnight = now.with(DayOfWeek.FRIDAY).with(LocalTime.MIDNIGHT);
                        if (now.isBefore(fridayMidnight)) {
                            //周报提报
                            reportService.createWeeklyTask(projectDO.getId());
                        }
                        //临时任务
                        tempTaskService.createTempTask(projectDO.getId());
                    }
                }
                if (!ObjectUtils.isEmpty(constructionStatusNow)) {
                    changeReviewDO.setConstructionAuditStatus(ProjectAuditStatusEnum.PASS.name());
                    projectDO.setConstructionStatus(constructionStatusNow);
                    changeReviewMapper.updateDO(changeReviewDO);
                    projectMapper.updateDO(projectDO);
                    //变更施工状态时调用该接口，用于周报判断是否生成该项目的周报任务
                    reportService.projectStatusChangeAdd(projectId,constructionStatusNow);
                    //添加施工状态变更时间轴
                    ProjectStatusAxisDO projectStatusAxisDO = new ProjectStatusAxisDO();
                    projectStatusAxisDO.setProjectId(projectId);
                    projectStatusAxisDO.setCreateTime(DateUtils.getNowDate());
                    projectStatusAxisDO.setStatus(constructionStatusNow);
                    projectStatusAxisDO.setCreateUser(userId);
                    axisService.save(projectStatusAxisDO);
                    if (verify(id)){
                        projectMapper.updateDO(aDo);
                    }
                    return true;
                } else {
                    return false;
                }
            } else if (!request.getConstructionAuditStatus()) {
                changeReviewDO.setConstructionAuditStatus(ProjectAuditStatusEnum.REJECT.name());
                changeReviewMapper.updateDO(changeReviewDO);
                if (verify(id)){
                    projectMapper.updateDO(aDo);
                }
                return true;
            }
        }
        Boolean shigongHeadPhoneAuditStatus = request.getShigongHeadPhoneAuditStatus();
        if (!ObjectUtils.isEmpty(shigongHeadNameAuditStatus)||!ObjectUtils.isEmpty(shigongHeadPhoneAuditStatus)) {
            if (!ObjectUtils.isEmpty(shigongHeadNameAuditStatus)) {
                if (shigongHeadNameAuditStatus) {
                    String headNameNow = request.getShigongHeadNameNow();
                    if (!ObjectUtils.isEmpty(headNameNow)) {
                        changeReviewDO.setShigongHeadNameAuditStatus(ProjectAuditStatusEnum.PASS.name());
                        projectDO.setShigongHeadName(headNameNow);
                        changeReviewMapper.updateDO(changeReviewDO);
                        projectMapper.updateDO(projectDO);
                        if (verify(id)) {
                            projectMapper.updateDO(aDo);
                        }
                    }
                } else if (!request.getShigongHeadNameAuditStatus()) {
                    changeReviewDO.setShigongHeadNameAuditStatus(ProjectAuditStatusEnum.REJECT.name());
                    changeReviewMapper.updateDO(changeReviewDO);
                    if (verify(id)) {
                        projectMapper.updateDO(aDo);
                    }
                }
            }

            if (!ObjectUtils.isEmpty(shigongHeadPhoneAuditStatus)) {
                if (shigongHeadPhoneAuditStatus) {
                    String headPhoneNow = request.getShigongHeadPhoneNow();
                    if (!ObjectUtils.isEmpty(headPhoneNow)) {
                        changeReviewDO.setShigongHeadPhoneAuditStatus(ProjectAuditStatusEnum.PASS.name());
                        projectDO.setShigongHeadPhone(headPhoneNow);
                        changeReviewMapper.updateDO(changeReviewDO);
                        projectMapper.updateDO(projectDO);
                        if (verify(id)){
                            projectMapper.updateDO(aDo);
                        }
                    }
                } else if (!request.getShigongHeadPhoneAuditStatus()) {
                    changeReviewDO.setShigongHeadPhoneAuditStatus(ProjectAuditStatusEnum.REJECT.name());
                    changeReviewMapper.updateDO(changeReviewDO);
                    if (verify(id)){
                        projectMapper.updateDO(aDo);
                    }
                }
            }
            return true;
        }

        Boolean shigongContactNameAuditStatus = request.getShigongContactNameAuditStatus();
        Boolean shigongContactPhoneAuditStatus = request.getShigongContactPhoneAuditStatus();
        if (!ObjectUtils.isEmpty(shigongContactNameAuditStatus)||!ObjectUtils.isEmpty(shigongContactPhoneAuditStatus)) {
            if (!ObjectUtils.isEmpty(shigongContactNameAuditStatus)) {
                if (shigongContactNameAuditStatus) {
                    String contactNameNow = request.getShigongContactNameNow();
                    if (!ObjectUtils.isEmpty(contactNameNow)) {
                        changeReviewDO.setShigongContactNameAuditStatus(ProjectAuditStatusEnum.PASS.name());
                        projectDO.setShigongContactName(contactNameNow);
                        changeReviewMapper.updateDO(changeReviewDO);
                        projectMapper.updateDO(projectDO);
                        if (verify(id)) {
                            projectMapper.updateDO(aDo);
                        }
                    }
                } else if (!request.getShigongContactNameAuditStatus()) {
                    changeReviewDO.setShigongContactNameAuditStatus(ProjectAuditStatusEnum.REJECT.name());
                    changeReviewMapper.updateDO(changeReviewDO);
                    if (verify(id)) {
                        projectMapper.updateDO(aDo);
                    }
                }
            }

            if (shigongContactPhoneAuditStatus) {
                String contactPhoneNow = request.getShigongContactPhoneNow();
                if (!ObjectUtils.isEmpty(contactPhoneNow)) {
                    changeReviewDO.setShigongContactPhoneAuditStatus(ProjectAuditStatusEnum.PASS.name());
                    projectDO.setShigongContactPhone(contactPhoneNow);
                    changeReviewMapper.updateDO(changeReviewDO);
                    projectMapper.updateDO(projectDO);
                    if (verify(id)){
                        projectMapper.updateDO(aDo);
                    }
                }
            } else if (!request.getShigongContactPhoneAuditStatus()) {
                changeReviewDO.setShigongContactPhoneAuditStatus(ProjectAuditStatusEnum.REJECT.name());
                changeReviewMapper.updateDO(changeReviewDO);
                if (verify(id)){
                    projectMapper.updateDO(aDo);
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 查询所有待审核的新项目
     * @return
     */
    @Override
    public Object selectNewProject(Long id) {
//        if (ObjectUtils.isEmpty(id)){
//            List<ProjectDO> projectDOList = projectMapper.selectAllNewProject();
//            return ProjectConvert.buildProjectVoList(projectDOList);
//        }
        ProjectDO projectDO = projectMapper.selectNewProject(id);
        return ProjectDtoMapper.INSTANCE.do2VO(projectDO);
    }

    /**
     * 云监管项目管理列表查询——查询所有审核通过的项目
     * @param request
     * @return
     */
    @Override
    public Object selectAllPassProject(ProjectRequest request, Pageable pageable) {
        PageHelper.startPage(request.getPageNum(),request.getPageSize()).setReasonable(true);
        List<ProjectDO> projectDOList = projectMapper.selectAllPassProject(request);
        PageInfo pageInfo = new PageInfo<>(projectDOList);
        List<ProjectVO> projectVOList = ProjectConvert.buildProjectVoList(projectDOList);
//        // 首先按 constructionStatus 分组，然后对每个分组进行排序
//        List<ProjectVO> sortedList = projectVOList.stream()
//                .sorted(Comparator.comparing(ProjectVO::getCreateTime).reversed())
//                .collect(Collectors.groupingBy(ProjectVO::getConstructionStatus))
//                .entrySet()
//                .stream()
//                .sorted(Comparator.comparingInt(entry -> getOrder(entry.getKey())))
//                .flatMap(entry -> entry.getValue().stream())
//                .collect(Collectors.toList());
        pageInfo.setList(projectVOList);
        return pageInfo;
    }

    // 定义 constructionStatus 的顺序
    private static int getOrder(String constructionStatus) {
        switch (constructionStatus) {
            case "RUNNING":
                return 1;
            case "WAIT_ACCEPT":
                return 2;
            case "FINISH":
                return 3;
            case "UN_START":
                return 4;
            case "DIE":
                return 5;
            case "STOP":
                return 6;
            default:
                return Integer.MAX_VALUE;
        }
    }

    /**
     * 查询所有待审核项目
     * @param request
     * @param pageable
     * @return
     */
    @Override
    public Object selectAllExamineProject(ProjectRequest request, Pageable pageable) {
        PageHelper.startPage(request.getPageNum(),request.getPageSize(),getOrderBy(pageable.getSort())).setReasonable(true);
        List<ProjectDO> projectDOList = projectMapper.selectAllExamineProject(request);
        PageInfo pageInfo = new PageInfo<>(projectDOList);
        List<ProjectVO> projectVOList = ProjectConvert.buildProjectVoList(projectDOList);
        pageInfo.setList(projectVOList);
        return pageInfo;
    }

    /**
     * 项目逻辑删除
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object delete(Long id) {
        ProjectDO projectDO = projectMapper.selectDOById(id);
        int i = projectMapper.deleteDOById(id);
        if (i<0){
            return false;
        }
        if (ProjectAuditTypeEnum.CHANGE.equals(projectDO.getAuditType())){
            int delete = changeReviewMapper.deleteByProjectId(id);
            if (delete<0){
                return false;
            }
        }
        return true;
    }

    /**
     * 项目审核待办事项提醒
     * @return
     */
    @Override
    public Integer selectWaitToBeDone() {
        ProjectRequest projectRequest = new ProjectRequest();
        List<ProjectDO> projectDOList = projectMapper.selectAllExamineProject(projectRequest);
        return projectDOList.size();
    }

    /**
     * 校验是否已完成项目信息变更审核
     * @param id
     */
    private Boolean verify(Long id) {
        ProjectChangeReviewDO changeReviewVO = changeReviewMapper.selectDOById(id);
        Boolean a = false;
        Boolean b = false;
        Boolean c = false;
        Boolean d = false;
        Boolean e = false;
        if (!ObjectUtils.isEmpty(changeReviewVO)) {
            if (!ObjectUtils.isEmpty(changeReviewVO.getConstructionStatusNow())) {
                a = ProjectAuditStatusEnum.PASS.name().equals(changeReviewVO.getConstructionAuditStatus())
                        || ProjectAuditStatusEnum.REJECT.name().equals(changeReviewVO.getConstructionAuditStatus());
            }else if (ObjectUtils.isEmpty(changeReviewVO.getConstructionStatusNow())&&ObjectUtils.isEmpty(changeReviewVO.getConstructionStatusOld())){
                a = true;
            }

            if (!ObjectUtils.isEmpty(changeReviewVO.getShigongHeadNameNow())) {
                b = ProjectAuditStatusEnum.PASS.name().equals(changeReviewVO.getShigongHeadNameAuditStatus())
                        || ProjectAuditStatusEnum.REJECT.name().equals(changeReviewVO.getShigongHeadNameAuditStatus());
            }else if (ObjectUtils.isEmpty(changeReviewVO.getShigongHeadNameNow())&&ObjectUtils.isEmpty(changeReviewVO.getShigongHeadNameOld())){
                b = true;
            }

            if (!ObjectUtils.isEmpty(changeReviewVO.getShigongHeadPhoneNow())) {
                c = ProjectAuditStatusEnum.PASS.name().equals(changeReviewVO.getShigongHeadPhoneAuditStatus())
                        || ProjectAuditStatusEnum.REJECT.name().equals(changeReviewVO.getShigongHeadPhoneAuditStatus());
            }else if (ObjectUtils.isEmpty(changeReviewVO.getShigongHeadPhoneNow())&&ObjectUtils.isEmpty(changeReviewVO.getShigongHeadPhoneOld())){
                c = true;
            }

            if (!ObjectUtils.isEmpty(changeReviewVO.getShigongContactNameNow())) {
                d = ProjectAuditStatusEnum.PASS.name().equals(changeReviewVO.getShigongContactNameAuditStatus())
                        || ProjectAuditStatusEnum.REJECT.name().equals(changeReviewVO.getShigongContactNameAuditStatus());
            }else if (ObjectUtils.isEmpty(changeReviewVO.getShigongContactNameNow())&&ObjectUtils.isEmpty(changeReviewVO.getShigongContactNameOld())){
                d = true;
            }

            if (!ObjectUtils.isEmpty(changeReviewVO.getShigongContactPhoneNow())) {
                e = ProjectAuditStatusEnum.PASS.name().equals(changeReviewVO.getShigongContactPhoneAuditStatus())
                        || ProjectAuditStatusEnum.REJECT.name().equals(changeReviewVO.getShigongContactPhoneAuditStatus());
            }else if (ObjectUtils.isEmpty(changeReviewVO.getShigongContactPhoneNow())&&ObjectUtils.isEmpty(changeReviewVO.getShigongContactPhoneOld())){
                e = true;
            }

        }
        if (a && b && c && d && e){
            return true;
        }
        return false;
    }

    private ProjectChangeReviewDO extracted(List<ProjectChangeReviewDO> changeReviewDO) {
        ProjectChangeReviewDO changeReview = changeReviewDO.stream().filter(review -> "WAIT".equals(review.getConstructionAuditStatus()) ||
                "WAIT".equals(review.getShigongContactNameAuditStatus()) ||
                "WAIT".equals(review.getShigongContactPhoneAuditStatus()) ||
                "WAIT".equals(review.getShigongHeadNameAuditStatus()) ||
                "WAIT".equals(review.getShigongHeadPhoneAuditStatus())).findFirst().orElse(null);
        return changeReview;
    }
}
